package com.chen.cloudpicture.manager;

import cn.hutool.core.io.FileUtil;
import com.chen.cloudpicture.config.CosClientConfig;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.PicOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 最通用的文件上传下载管理类
 * 操作对象存储
 */
@Component
public class CosManager {

    @Resource
    private CosClientConfig cosClientConfig;
    @Resource
    private COSClient cosClient;

    /**
     * 上传文件
     *
     * @param key  文件在存储桶中的唯一键
     * @param file 要上传的本地文件对象
     */
    public PutObjectResult putObject(String key, File file) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key,
                file);
        return cosClient.putObject(putObjectRequest);
    }

    /**
     * 下载对象
     * 文件下载有四种方式
     * 官方文档两种：
     * 1. 对象存储 => 后端(保存文件) => 前端
     * 2. 对象存储 => 后端(返回文件流) => 前端   （节省开销，提高性能）
     * 企业常用：
     * 3. 后端(校验权限，提供临时权限) => 前端(直接访问对象存储) （性能最高）
     * 4. 直接通过 URL 路径链接访问，适合公开的资源，我们的项目就是适合这种方式。
     * <p>
     * 这里演示第二种方式
     *
     * @param key 文件在存储桶中的唯一键
     */
    public COSObject getObject(String key) {
        GetObjectRequest getObjectRequest = new GetObjectRequest(cosClientConfig.getBucket(), key);
        return cosClient.getObject(getObjectRequest);
    }

    /**
     * 上传图片（附带图片信息）
     *
     * 图片上传优化：图片压缩
     * 图片压缩方式：1.将图片格式转换为体积更小的格式，比如 WebP 或 AVI؜F；2.对图片质量进行压缩（有损压缩）3.缩小图片尺寸 推荐第一种
     * 一般有两种压缩格式：WebP和 AVI؜F，AVI؜F虽然压缩率更高一点但是兼容性不然WEBP，所以使用前者
     * 用云服务提供SDK进行图片压缩就可以（腾讯云的数据万象服务）
     *
     * 图片加载优化：首页展示缩略图
     * 首页展示较小尺寸的图片，点开图片才会展示原图。这样在首页加载图片速度可以提升非常多(好几倍)，
     * 因为原图一般都很大，比缩略图大几倍十几倍。直接加载原图加载时间长，网络流量消耗多。
     * 也是依靠腾讯云数据万象实现，给图片添加缩略处理规则就行
     *
     * @param key  文件在存储桶中的唯一键
     * @param file 要上传的本地文件对象
     */
    public PutObjectResult putPictureObject(String key, File file) {
        // PutObjectRequest对象，封装文件上传的信息
        PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key,
                file);
        // 对图片进行处理（获取图片信息也被视作一种处理）
        // PicOperations是腾讯云提供的处理图片的类
        PicOperations picOperations = new PicOperations();
        // 1表示返回原图信息，如尺寸，格式，大小等。0则不返回
        picOperations.setIsPicInfo(1);

        //图片处理规则列表
        List<PicOperations.Rule> rules = new ArrayList<>();
        // 1.图片压缩规则（转成WebP格式）
        String webpKey = FileUtil.mainName(key) + ".webp";
        PicOperations.Rule compressRule = new PicOperations.Rule();
        compressRule.setFileId(webpKey);
        compressRule.setBucket(cosClientConfig.getBucket());
        //compressRule.setRule("imageMogr2/format/webp");
        // 添加thumbnail参数设置最小宽高，确保至少512x512，保持比例（主要为了适应AI扩图图片最小大小要求）
        compressRule.setRule("imageMogr2/thumbnail/!512x512r/min/format/webp");
        rules.add(compressRule);
        // 2.缩略图处理规则 ,仅对 > 20KB的图片生成缩略图
        if(file.length() > 20 * 1024){
            PicOperations.Rule thumbnailRule = new PicOperations.Rule();
            // 拼接缩略图的路径
            String thumbnailKey = FileUtil.mainName(key) + "_thumbnail." + FileUtil.getSuffix(key);
            thumbnailRule.setFileId(thumbnailKey);
            thumbnailRule.setBucket(cosClientConfig.getBucket());
            // 缩放规则 /thumbnail/<Width>x<Height>>（如果大于原图宽高，则不处理）
            thumbnailRule.setRule(String.format("imageMogr2/thumbnail/%sx%s>", 256, 256));
            rules.add(thumbnailRule);
        }
        // 构造处理参数，将图片处理操作配置添加到文件上传请求中
        picOperations.setRules(rules);
        putObjectRequest.setPicOperations(picOperations);
        return cosClient.putObject(putObjectRequest);
    }

    /**
     * 删除对象存储文件
     *
     * @param key 文件 key
     */
    public void deleteObject(String key) throws CosClientException {
        cosClient.deleteObject(cosClientConfig.getBucket(), key);
    }


}
